home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / DialogControls / DialogControls.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  24KB  |  874 lines

  1. /******************************************************************************
  2.  DialogControls.c by Todd Clements (tclement@hmc.edu)
  3.     This demo shows how to do different things with dialogs:
  4.         1) Set the window font and size
  5.         2) Patch NewControl() so that you have controls in the window font
  6.             (thanks to Jens Alfke <jens_alfke@powertalk.apple.com> for the code)
  7.         3) Use Popup Menus in modal dialogs
  8.         4) Use AppendDITL() to get a NewsWatcher-like preferences box
  9.         5) Use styled text edit records from resources to display text
  10.         6) Write a filter for a ModalDialog
  11.         7) Use MovableModal dialog boxes
  12.         
  13.     Some some of this code is stolen from my own program, others stolen from other
  14.     people, but it's all here for you!
  15.     
  16.     If you have any comments about the code, any improvements/additions/bugs,
  17.     please feel free to contact me at the above address.
  18.     
  19.     I make no guarantees regarding the decency of this code.  Run it and use
  20.     it at your own risk.
  21.     
  22.     January 26, 1995    -    1.0 - First release
  23.     May 9, 1995            -    1.1 - Second release
  24.                                     Changed to MovableModal dialog box
  25.                                     Added "Reset Panel to Defaults" button
  26.                                     Disabled controls when window deactivated
  27. ******************************************************************************/
  28.  
  29.  
  30. #include "DialogControls.h"
  31. #include "Functions.h"
  32. #include "PatchNewControl.h"
  33. #include "MyMenus.h"
  34. #include "MovableModal.h"
  35.  
  36. /******************************************************************************
  37.     Comments about the resource file for DialogControls.c
  38.     
  39.     The heights of the control items in my dialog have been adjusted to reflect
  40.     the smaller size of the geneva font.  There is probably a standard size I
  41.     should use, but I didn't bother to look it up.  If you care, you should probably
  42.     look it up.  (But, if you care, you'll know that Apple tells you not to use
  43.     custom fonts for control items (although, see just about any System 7.5 control
  44.     panel, and then scratch your head...))
  45.     
  46.     All the controls in the dialog box are the same width, per Apple HIGs (Human
  47.     Interface Guidelines).  This is so that for scripts that read from right
  48.     to left, the controls will appear correctly.
  49.     
  50.     See the note in CheckHamburgerItems() about the true grey in dimmed controls.
  51.     
  52.     Note that the procIDs for the popup menus are different.  1008 is for a standard
  53.     popup.  1016 is for a popup in the window font.
  54. ******************************************************************************/
  55.  
  56. #define        pbOK            1
  57. #define        pbCancel        2
  58. #define        pbRevert        9
  59.  
  60. #define        rFirstOutline    4
  61. #define        rLastOutline    8
  62.  
  63. /** Defines for the menus **/
  64. #define        mApple            128
  65. #define        mFile            129
  66. #define        mEdit            130
  67.  
  68. #define        miAbout            1
  69.  
  70. #define        miOpen            1
  71. #define        miClose            2
  72. #define        miQuit            7
  73.  
  74. #define        popmiHotDog        1
  75. #define        popmiHamburger    2
  76.  
  77. /** Defines for the two windows that have stuff in them **/
  78.  
  79. #define        ditlHamburger    301
  80. #define        ditlHotDog        300
  81.  
  82. #define        wPreferences    128
  83.  
  84. #define        popWhichFood    3
  85.  
  86. /* This is for hamburger */
  87. #define        rbBeef        1
  88. #define        rbChicken    2
  89. #define        rbOther        3
  90. #define        cbLie        4
  91. #define        cbHamRelish    5
  92. #define        cbHamOnion    6
  93. #define        cbHamKetchup    7
  94. #define        cbHamMustard    8
  95. #define        cbHamTomato        9
  96. #define        cbHamLettuce    10
  97. #define        cbHamPickle        11
  98.  
  99. /* This is for hot dog */
  100. #define        rbChargeThroughNose    1
  101. #define        rbBeReasonable        2
  102. #define        rbArmAndLeg            3
  103. #define        rbGiveAway            4
  104. #define        cbHotRelish            5
  105. #define        cbHotOnion            6
  106. #define        cbHotKetchup        7
  107. #define        cbHotMustard        8
  108. #define        popHotType            9
  109.  
  110. #define        popmiRegular        1
  111. #define        popmiPolish            2
  112. #define        popmiKosher            3
  113. #define        popmiVeggie            4
  114.  
  115.  
  116. FoodPtr            food;                // Variable storing all checkbox/radio button information
  117. Boolean            gDone = false;        // Should the program terminate?
  118. EventRecord        event;                // The event
  119. TEHandle        aboutText;            // Handle to the text edit record (we need it in various places)
  120.  
  121.  
  122. /** This is where all the meat to the program is. =) **/
  123. void    main( void )
  124. {
  125.     InitToolBox();
  126.     SetUpGlobals();
  127.     SetupMenus();
  128.     EventLoop();
  129. }
  130.  
  131.  
  132.  
  133. /** Just your standard routines here **/
  134. void     InitToolBox( void )
  135. {
  136.     InitGraf(&(qd.thePort));
  137.     InitFonts();
  138.     InitWindows();
  139.     InitMenus();
  140.     TEInit();
  141.     InitDialogs(0L);    // I don't remember if this is supposed to be something else…
  142.     InitCursor();
  143.  
  144.     MaxApplZone();
  145.     MoreMasters();
  146.     MoreMasters();
  147. }
  148.  
  149.  
  150. /** Allocate memory for, and initialize our global memory. **/
  151. void    SetUpGlobals( void )
  152. {
  153.     food = (FoodPtr) NewPtr( sizeof( Food ) );
  154.     if( !food ) /* We're all left hungry */
  155.     {
  156.         SysBeep( 10 );
  157.         ExitToShell();
  158.     }
  159.     
  160.     DefaultHotDogSettings( food );
  161.     DefaultHamburgerSettings( food );
  162.  
  163. }
  164.  
  165.  
  166. /** Set the defaults for the Hot Dog settings.  Used for
  167.     initialization and "Reset" button.                    **/
  168. void    DefaultHotDogSettings( FoodPtr theFood )
  169. {
  170.     theFood->hotDog.price = rbGiveAway;
  171.     theFood->hotDog.relish = true;
  172.     theFood->hotDog.onion = true;
  173.     theFood->hotDog.ketchup = true;
  174.     theFood->hotDog.mustard = false;
  175.     theFood->hotDog.hotType = popmiRegular;
  176. }
  177.  
  178.  
  179. /** Set the defaults for the Hamburger settings.  Used for
  180.     initialization and "Reset" button.                    **/
  181. void    DefaultHamburgerSettings( FoodPtr theFood )
  182. {
  183.     theFood->ham.hamType = rbBeef;
  184.     theFood->ham.lie = false;
  185.     theFood->ham.relish = true;
  186.     theFood->ham.onion = true;
  187.     theFood->ham.ketchup = true;
  188.     theFood->ham.mustard = false;
  189.     theFood->ham.tomato = false;
  190.     theFood->ham.lettuce = true;
  191.     theFood->ham.pickle = true;
  192. }
  193.  
  194.  
  195. /** Get the menus from the resource and display them. **/
  196. void    SetupMenus( void )
  197. {
  198.     Handle        menuBar;
  199.     MenuHandle    menu;
  200.     
  201.     menuBar = GetNewMBar( 128 );
  202.     if( menuBar == nil )
  203.     {
  204.         SysBeep( 10 ); /* Probably should display error */
  205.         ExitToShell();
  206.     }
  207.     
  208.     SetMenuBar( menuBar );
  209.     
  210.     menu = GetMenuHandle( 128 );
  211.     AppendResMenu( menu, 'DRVR' );
  212.     
  213.     // MenuEnable is my own function (see Functions.c) that allows you to use the menu resource number
  214.     // followed by the menu item to enable/disable menu items.  0 as the menu item means the menu itself.
  215.     // You'll see a lot of my canned functions throughout this program.
  216.     MenuEnable( mEdit, 0, false );
  217.     MenuEnable( mFile, miClose, false ); /* We have no use for this menu item*/
  218.     
  219.     DrawMenuBar();
  220. }
  221.  
  222. /** Where everything exciting gets passed on to other people **/
  223. void    EventLoop( void )
  224. {
  225.     while( !gDone )
  226.     {
  227.         if( WaitNextEvent( everyEvent, &event, 60, nil ) )
  228.         {
  229.             switch( event.what )
  230.             {
  231.                 case    mouseDown:
  232.                     HandleMouseDown( );
  233.                     break;
  234.                 case    keyDown:
  235.                     HandleKeyDown( );
  236.                     break;
  237.                 case    activateEvt:
  238.                 case    autoKey:
  239.                 case    updateEvt:
  240.                     break;
  241.                 default:
  242.                     break;
  243.                     
  244.             }
  245.         }
  246.     }
  247. }
  248.  
  249.  
  250. /** Did someone press the mouse?
  251.     This function doesn't do much because, well, this program doesn't do much.
  252.     However, a lot of the switches were left in so you could just add your own code
  253.     if you wanted to. **/
  254. void    HandleMouseDown( void )
  255. {
  256.     short        code;
  257.     WindowPtr    window;
  258.     GrafPtr        thePort;
  259.     
  260.     code = FindWindow( event.where, &window );
  261.     
  262.     switch( code )
  263.     {
  264.         case    inMenuBar:
  265.             InterpretMenu( );
  266.             break;
  267.         case    inSysWindow:
  268.             GetPort( &thePort );
  269.             SystemClick( &(event), window );
  270.             SetPort( thePort );
  271.             break;
  272.         case     inDrag:                        //    These are here to show possible
  273.         case     inGoAway:                    //    events you could handle.  I'm
  274.         case    inContent:                    //    completely modal, so I don't
  275.         case     inGrow:                        //    have to handle them. 
  276.         case     inZoomIn: case     inZoomOut:
  277.             break;
  278.         default:
  279.             break;
  280.     }
  281. }
  282.  
  283.  
  284. /** A key was pressed.
  285.     All we care about here is if the key is a menu item equivalent.  If it is, pass
  286.     it to our menu handling function. **/
  287. void    HandleKeyDown( void )
  288. {
  289.     int        menu, menuItem;
  290.     long    theMenu;
  291.  
  292.     if(( event.modifiers & cmdKey ) != 0 )
  293.     {
  294.         theMenu = MenuKey( event.message & charCodeMask );
  295.         menu = HiWord( theMenu );
  296.         menuItem = LoWord( theMenu );
  297.         HiliteMenu( menu );
  298.         HandleMenu( menu, menuItem );
  299.     }
  300. }
  301.  
  302. /** If there was a mouseDown in a menu, we have to find out which menu item was selected. **/
  303. void    InterpretMenu( void )
  304. {
  305.     long    menuChoice;
  306.     
  307.     menuChoice = MenuSelect( event.where );
  308.     DoThisMenu( menuChoice );
  309. }
  310.  
  311. /** If the user chose a desk accessory, launch it. **/
  312. void    HandleDeskAccessory( int    menuItem )
  313. {
  314.     Str255        accName;
  315.     
  316.     MenuHandle    appleMenu = GetMenuHandle( 128 );
  317.     GetMenuItemText( appleMenu, menuItem, accName );
  318.     OpenDeskAcc( accName );
  319. }
  320.  
  321. /** Needed for the MovableModal thing…it breaks a menu code into a menu and a menu item. **/
  322. void    DoThisMenu( long menuCode )
  323. {
  324.     int        theMenu;
  325.     int        theMenuItem;
  326.     
  327.     theMenu = HiWord( menuCode );
  328.     theMenuItem = LoWord( menuCode );
  329.     
  330.     HandleMenu( theMenu, theMenuItem );
  331. }
  332.  
  333.  
  334. /** Here is where we give away all the menu power. **/
  335. void     HandleMenu( int menu, int menuItem )
  336. {
  337.     switch( menu )
  338.     {
  339.         case mApple:
  340.             switch( menuItem )
  341.             {
  342.                 case 1:
  343.                     DoAboutMenu();
  344.                     break;
  345.                 default:
  346.                     HandleDeskAccessory( menuItem );
  347.                     break;
  348.             }
  349.             break;
  350.         case mFile:
  351.             switch(menuItem)
  352.             {
  353.                 case miQuit:
  354.                     gDone = true;
  355.                     break;
  356.                 case miOpen:
  357.                     DoTheMagic();
  358.                     break;
  359.                 default:
  360.                     break;
  361.             }
  362.             break;
  363.         case mEdit:
  364.             break;
  365.         default:
  366.             break;
  367.     }
  368.     // The menu manager hilites the menu, but waits for you to unhilite it.
  369.     HiliteMenu( 0 );
  370. }
  371.  
  372.  
  373. /** The about menu simply puts up a styled text block and waits for a click. **/
  374. void    DoAboutMenu( void )
  375. {
  376.     Rect        firstRect;
  377.     Handle        firstText;
  378.     StScrpHandle styleHdl;
  379.     DialogPtr    aboutPtr;
  380.     short        hit;
  381.     Boolean        done = false;
  382.     ModalFilterUPP    filter;
  383.     
  384.     // You have to use this function if you are going to be compiling for the PowerPC.
  385.     // In the 68K realm, you can still pass AboutFilter itself to ModalDialog(), but
  386.     // this is the new way of doing it.  It works on both platforms since the compiler
  387.     // knows what to do on either platform.
  388.     filter = NewModalFilterProc( AboutFilter );
  389.     if( !filter ) return;
  390.     
  391.     // Get a new dialog, and set the font of the dialog
  392.     aboutPtr = MyGetNewDialogFont( 129, true, nil, geneva, 10 );
  393.     
  394.     if( aboutPtr  == nil )
  395.     {    SysBeep( 10 ); return; }
  396.     
  397.     // Canned routine - get the rect of a dialog item
  398.     GetDialogItemRect( aboutPtr, 1, &firstRect );
  399.     
  400.     // Create our TextEdit record
  401.     aboutText = TEStyleNew( &firstRect, &firstRect );
  402.  
  403.     // Center the text
  404.     TESetAlignment( teCenter, aboutText );
  405.  
  406.     // Look to see if we can find the text we want in the resource.  If we can't, beep
  407.     // angrily, and return.
  408.     firstText = GetResource( 'TEXT', 128 );
  409.     if( !firstText )
  410.     {
  411.         SysBeep( 10 );
  412.         DisposeDialog( aboutPtr );
  413.         return;
  414.     }
  415.  
  416.     HLock( firstText );
  417.  
  418.     // Get our style record that matches our text record
  419.     styleHdl = (StScrpHandle)(GetResource( 'styl', 128 ) );
  420.     if( styleHdl )
  421.     {
  422.         // If the style was there, insert it and the text
  423.         TEStyleInsert( *firstText, GetResourceSizeOnDisk(firstText), styleHdl, aboutText );
  424.     }
  425.     else
  426.     {
  427.         // If the style was not there, insert the text all by itself.
  428.         TEInsert( *firstText, GetResourceSizeOnDisk( firstText ), aboutText );
  429.     }
  430.  
  431.     HUnlock( firstText );
  432.  
  433.     // Make sure there is an update event generated.
  434.     // The Window Manager will automatically create an update event, but this is to be safe
  435.     InvalRect( &firstRect );
  436.     
  437.     // Always use ReleaseResource() on resource handles, not DisposeHandle()!
  438.     ReleaseResource( (Handle) firstText );
  439.     ReleaseResource( (Handle) styleHdl );
  440.     
  441.     // Simply wait for a click
  442.     while( !done )
  443.     {
  444.         ModalDialog( filter, &hit );
  445.         {
  446.             if( hit != 0 )
  447.             {
  448.                 TEDispose( aboutText );
  449.                 DisposeDialog( aboutPtr );
  450.                 done = true;
  451.             }
  452.         }
  453.     }
  454.     
  455.     // Always be kind to your memory!
  456.     DisposeRoutineDescriptor( (UniversalProcPtr) AboutFilter );
  457. }
  458.  
  459. /** This is our very simple filter for the about box.  It doesn't do much except check
  460.     for updateEvents, but you can add anything you want to it, including stuff it would
  461.     do during idle time (like scroll some text (See MovieScroll.c from Ken Long) **/
  462. pascal Boolean AboutFilter(DialogPtr inputDialog, EventRecord *myDialogEvent, short *theDialogItem)
  463. {
  464.     Boolean    returnVal = false;
  465.  
  466.     switch( myDialogEvent->what )
  467.     {
  468.         case updateEvt:            // This is all we care about
  469.         {
  470.             Rect        rect;
  471.             
  472.             BeginUpdate( inputDialog );
  473.             GetDialogItemRect( inputDialog, 1, &rect );
  474.             TEUpdate( &rect, aboutText );
  475.             EndUpdate( inputDialog );
  476.             returnVal = true;
  477.             *theDialogItem = 0;
  478.         }
  479.         break;
  480.         default:
  481.             break;
  482.     }
  483.     
  484.     return returnVal;    // Tell the Dialog Manager whether we handled this event or not.
  485. }
  486.  
  487.  
  488. /** This is what we're really here for, though, folks! **/
  489. void    DoTheMagic( void )
  490. {
  491.     DialogPtr        dialog;
  492.     short            whichFood = popmiHotDog;
  493.     short            standardDITL;    /* number of items in standar DITL for our window */
  494.     Food            newFood;        /* Copy this so we can allow a cancel */
  495.     Boolean            done = false;
  496.     short            hit;
  497.     short            itemType;
  498.     Handle            foodPopHandle;
  499.     Rect            foodPopRect;
  500.     short            newValue;
  501.     
  502.     // A very useful routine.  It makes it so that all controls that are check boxes and
  503.     // radio buttons (you can change it if you like) use the current window font.
  504.     PatchNewControl();
  505.     
  506.     // Canned routine for getting a dialog box and setting the font as well
  507.     dialog = MyGetNewDialogFont( 128, true, nil, geneva, 10 );
  508.     
  509.     if( !dialog )
  510.     {
  511.         SysBeep( 10 );
  512.         return;
  513.     }
  514.     
  515.     // Set the menus for a movable modal dialog box
  516.     MovableModalMenus();
  517.     
  518.     SetDialogDefaultItem( dialog, pbOK );
  519.     SetDialogCancelItem( dialog, pbCancel );
  520.     
  521.     // Copy our variables so that we are only changing temporary ones
  522.     BlockMove( food, &newFood, sizeof( Food ) );
  523.  
  524.     // We could just use SnatchHandle here, but I decided not to for some odd reason
  525.     GetDialogItem( dialog, popWhichFood, &itemType, &foodPopHandle, &foodPopRect );
  526.     SetControlValue( (ControlHandle) foodPopHandle, whichFood );
  527.  
  528.     // Count the number of items we have in our dialog before we add new ones
  529.     standardDITL = CountDITL( dialog );
  530.  
  531.     // Add the correct DITL (based on whichFood), and check the correct stuff
  532.     SetUpFoodDitl( dialog, standardDITL, whichFood, &newFood );
  533.  
  534.     // We aren't doing drawing routines here because when a dialog is put up, it
  535.     // automatically generates an updateEvt, so you don't have to deal with it specifically.
  536.         
  537.     while( !done )
  538.     {
  539.         MovableModalDialog( 0L, &hit, dialog );
  540.         
  541.         switch( hit )
  542.         {
  543.             case pbOK:
  544.                 BlockMove( &newFood, food, sizeof( Food ) );
  545.                 done = true;
  546.                 break;
  547.             case pbCancel:
  548.                 done = true;
  549.                 break;
  550.             case popWhichFood:
  551.                 GetDialogItem( dialog, popWhichFood, &itemType, &foodPopHandle, &foodPopRect );
  552.                 newValue = GetControlValue( (ControlHandle) foodPopHandle );
  553.                 if( whichFood == newValue )
  554.                     break;
  555.                 else
  556.                 {
  557.                     whichFood = newValue;
  558.                     TakeOutCurrentDITL( dialog, standardDITL );
  559.                     SetUpFoodDitl( dialog, standardDITL, whichFood, &newFood );
  560.                 }
  561.             
  562.                 break;
  563.             default:
  564.                 switch( whichFood )
  565.                 {
  566.                     case popmiHotDog:
  567.                         HandleHotDogItems( dialog, standardDITL, &newFood, hit );
  568.                         break;
  569.                     case popmiHamburger:
  570.                         HandleHamburgerItems( dialog, standardDITL, &newFood, hit );
  571.                         break;
  572.                 }
  573.                 break;
  574.         }
  575.     }
  576.  
  577.     UnPatchNewControl();
  578.     TwiddleMenus();
  579.  
  580.     DisposeDialog( dialog );
  581.  
  582. }
  583.  
  584. /* I use this as a quick way to get a new dialog, put it behind any window I want,
  585.     as well as set the window font all in one fell swoop. */
  586. DialogPtr    MyGetNewDialogFont( int    rsrcId, Boolean moveToFront, WindowPtr behindWhich,
  587.                     short fontNo, short textSize )
  588. {
  589.     DialogPtr        window;
  590.     
  591.     if( moveToFront ) behindWhich = (WindowPtr) -1L;
  592.  
  593.     window = GetNewDialog( rsrcId, nil, behindWhich );
  594.     
  595.     if( !window )
  596.     {
  597.         SysBeep( 10 );
  598.         return nil;
  599.     }
  600.  
  601.     SetWRefCon( window, (long) rsrcId );
  602.     SetPort( (GrafPtr) window );
  603.     
  604.     SetDialogFontAndSize( window, fontNo, textSize );
  605.     
  606.     ShowWindow( window );
  607.     return window;
  608. }
  609.  
  610. /* Also stolen from an unknown source */
  611. void    SetDialogFontAndSize( DialogPtr theDialog, short fontNo, short fontSize )
  612. {
  613.     FontInfo    fInfo;
  614.  
  615.     TextFont( fontNo );
  616.     TextSize( fontSize );
  617.     GetFontInfo( &fInfo );
  618.     
  619.     (**(((DialogPeek)theDialog)->textH)).txFont = geneva;
  620.     (**(((DialogPeek)theDialog)->textH)).txSize = 9;
  621.     
  622.     (**(((DialogPeek)theDialog)->textH)).lineHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
  623.     (**(((DialogPeek)theDialog)->textH)).fontAscent = fInfo.ascent;
  624. }
  625.  
  626. /** Frame the options area **/
  627. void    FrameOptions( DialogPtr dialog )
  628. {
  629.     int        i;
  630.     Rect    theRect;
  631.     
  632.     for( i = rFirstOutline; i <= rLastOutline; i++ )
  633.     {
  634.         GetDialogItemRect( dialog, i, &theRect );
  635.         FrameRect( &theRect );
  636.     }
  637. }
  638.  
  639. /** Add the correct DITLs, and then call the checking procedure **/
  640. void    SetUpFoodDitl( DialogPtr window, short standardDITL, short whichFood, FoodPtr newFood )
  641. {
  642.     Handle        addDitl;
  643.     
  644.     addDitl = GetResource( 'DITL', whichFood + ditlHotDog - 1 );
  645.     if( !addDitl )
  646.     {
  647.         SysBeep( 10 );
  648.         ExitToShell();
  649.     }
  650.     
  651.     HLock( addDitl );
  652.     AppendDITL( window, addDitl, overlayDITL );
  653.     HUnlock( addDitl );
  654.     ReleaseResource( addDitl );
  655.     
  656.     SelectTheRightStuff( window, standardDITL, whichFood, newFood );
  657. }
  658.  
  659. /** Remove the current EXTRA items in the dialog box, to set up for the next one **/
  660. void    TakeOutCurrentDITL( DialogPtr window, short standardDITL )
  661. {
  662.     short        ditlCount;
  663.     
  664.     ditlCount = CountDITL( window );
  665.     
  666.     ShortenDITL( window, ditlCount - standardDITL );
  667. }
  668.  
  669. /** Just sees which item we wish to go through and make sure everything is checked for **/
  670. void    SelectTheRightStuff( DialogPtr window, short standardDITL, short whichFood, FoodPtr newFood )
  671. {
  672.     switch( whichFood )
  673.     {
  674.         case popmiHotDog:
  675.             CheckHotDogItems( window, whichFood, standardDITL, newFood );
  676.             break;
  677.         case popmiHamburger:
  678.             CheckHamburgerItems( window, whichFood, standardDITL, newFood );
  679.             break;
  680.         default:
  681.             break;
  682.     }
  683. }
  684.  
  685.  
  686. /** The following two routines simply select the right items in the dialog box depending
  687.     on the values of the variables **/
  688. void    CheckHotDogItems( DialogPtr window, short whichFood, short standardDITL, FoodPtr newFood )
  689. {
  690.     short        itemType;
  691.     Handle        foodPopHandle;
  692.     Rect        foodPopRect;
  693.     short        i;
  694.     
  695.     /* Make the popup list point to the right thing */
  696.     GetDialogItem( window, popHotType+standardDITL, &itemType, &foodPopHandle, &foodPopRect );
  697.     SetControlValue( (ControlHandle) foodPopHandle, newFood->hotDog.hotType );
  698.     
  699.     // Check the radio buttons appropriately
  700.     for( i = rbChargeThroughNose; i <= rbGiveAway; i++ )
  701.         SelectButton( window, i+standardDITL, i == newFood->hotDog.price );
  702.  
  703.     // Do button stuff
  704.     SelectButton( window, cbHotRelish+standardDITL, newFood->hotDog.relish );
  705.     SelectButton( window, cbHotOnion+standardDITL, newFood->hotDog.onion );
  706.     SelectButton( window, cbHotKetchup+standardDITL, newFood->hotDog.ketchup );
  707.     SelectButton( window, cbHotMustard+standardDITL, newFood->hotDog.mustard );
  708. }
  709.  
  710. void    CheckHamburgerItems( DialogPtr window, short whichFood, short standardDITL, FoodPtr newFood )
  711. {
  712.     short        i;
  713.     
  714.     for( i = rbBeef; i <= rbOther; i++ )
  715.         SelectButton( window, i+standardDITL, i == newFood->ham.hamType );
  716.  
  717.     SelectButton( window, cbHamRelish+standardDITL, newFood->ham.relish );
  718.     SelectButton( window, cbHamOnion+standardDITL, newFood->ham.onion );
  719.     SelectButton( window, cbHamKetchup+standardDITL, newFood->ham.ketchup );
  720.     SelectButton( window, cbHamMustard+standardDITL, newFood->ham.mustard );
  721.     SelectButton( window, cbHamTomato+standardDITL, newFood->ham.tomato );
  722.     SelectButton( window, cbHamLettuce+standardDITL, newFood->ham.lettuce );
  723.     SelectButton( window, cbHamPickle+standardDITL, newFood->ham.pickle );
  724.     
  725.     SelectButton( window, cbLie+standardDITL, (newFood->ham.hamType == rbOther && newFood->ham.lie ) );
  726.     
  727.     // EnableButton is very interesting.  You will note (those of you with color Macs) that
  728.     // the "Lie about contents" button greyed in TRUE grey, not in the fake grey pattern
  729.     // that we are used to seeing.  This is because I created a custom color table for my
  730.     // dialog box.  This made the Dialog Manger know that we had a full color dialog
  731.     // box, and so it knew to display in real rather than fake grey.  All you have to do
  732.     // is choose "Custom" in the "Window Colors" part of the dialog box editor in ResEdit,
  733.     // change one item, and change it back.  Then, all of your controls will be properly greyed
  734.     // without any extra code.
  735.     EnableButton( window, cbLie+standardDITL, newFood->ham.hamType == rbOther );
  736. }
  737.  
  738. /** Handle it if we clicked somewhere when the HotDog items DITL was up **/
  739. void    HandleHotDogItems( DialogPtr window, short standardDITL, FoodPtr newFood, short hit )
  740. {
  741.     if ( hit == pbRevert )
  742.     {
  743.         DefaultHotDogSettings( newFood );
  744.         CheckHotDogItems( window, 0, standardDITL, newFood );
  745.         return;
  746.     }
  747.     
  748.     switch( hit - standardDITL)
  749.     {
  750.         case rbChargeThroughNose: case rbBeReasonable: case rbArmAndLeg: case rbGiveAway:
  751.             SelectButton( window, newFood->hotDog.price+standardDITL, false );
  752.             newFood->hotDog.price = hit-standardDITL;
  753.             SelectButton( window, newFood->hotDog.price+standardDITL, true );
  754.             break;
  755.         case cbHotRelish:
  756.             CheckButton( window, cbHotRelish+standardDITL );
  757.             newFood->hotDog.relish = !(newFood->hotDog.relish);
  758.             break;
  759.         case cbHotOnion:
  760.             CheckButton( window, cbHotOnion+standardDITL );
  761.             newFood->hotDog.onion = !(newFood->hotDog.onion);
  762.             break;
  763.         case cbHotKetchup:
  764.             CheckButton( window, cbHotKetchup+standardDITL );
  765.             newFood->hotDog.ketchup = !(newFood->hotDog.ketchup);
  766.             break;
  767.         case cbHotMustard:
  768.             CheckButton( window, cbHotMustard+standardDITL );
  769.             newFood->hotDog.mustard = !(newFood->hotDog.mustard);
  770.             break;
  771.         case popHotType:
  772.             {short        itemType;
  773.             Handle        foodPopHandle;
  774.             Rect        foodPopRect;
  775.             GetDialogItem( window, popHotType+standardDITL, &itemType, &foodPopHandle, &foodPopRect );
  776.             newFood->hotDog.hotType = GetControlValue( (ControlHandle) foodPopHandle );
  777.             }break;
  778.     }
  779. }
  780.  
  781.  
  782. void    HandleHamburgerItems( DialogPtr window, short standardDITL, FoodPtr newFood, short hit )
  783. {
  784.     if ( hit == pbRevert )
  785.     {
  786.         DefaultHamburgerSettings( newFood );
  787.         CheckHamburgerItems( window, 0, standardDITL, newFood );
  788.         return;
  789.     }
  790.  
  791.     switch( hit - standardDITL)
  792.     {
  793.         case rbBeef: case rbChicken: case rbOther:
  794.             SelectButton( window, newFood->ham.hamType+standardDITL, false );
  795.             SelectButton( window, hit, true );
  796.             newFood->ham.hamType = hit-standardDITL;
  797.             if( newFood->ham.hamType == rbOther )
  798.                 EnableButton( window, cbLie+standardDITL, true );
  799.             else
  800.             {
  801.                 EnableButton( window, cbLie+standardDITL, false );
  802.                 newFood->ham.lie = false;
  803.                 SelectButton( window, cbLie+standardDITL, false );
  804.             }
  805.             break;
  806.         case cbLie:
  807.             CheckButton( window, cbLie+standardDITL );
  808.             newFood->ham.lie = !(newFood->ham.lie);
  809.             break;
  810.         case cbHamRelish:
  811.             CheckButton( window, cbHamRelish+standardDITL );
  812.             newFood->ham.relish = !(newFood->ham.relish);
  813.             break;
  814.         case cbHamOnion:
  815.             CheckButton( window, cbHamOnion+standardDITL );
  816.             newFood->ham.onion = !(newFood->ham.onion);
  817.             break;
  818.         case cbHamKetchup:
  819.             CheckButton( window, cbHamKetchup+standardDITL );
  820.             newFood->ham.ketchup = !(newFood->ham.ketchup);
  821.             break;
  822.         case cbHamMustard:
  823.             CheckButton( window, cbHamMustard+standardDITL );
  824.             newFood->ham.mustard = !(newFood->ham.mustard);
  825.             break;
  826.         case cbHamTomato:
  827.             CheckButton( window, cbHamTomato+standardDITL );
  828.             newFood->ham.tomato = !(newFood->ham.tomato);
  829.             break;
  830.         case cbHamLettuce:
  831.             CheckButton( window, cbHamLettuce+standardDITL );
  832.             newFood->ham.lettuce = !(newFood->ham.lettuce);
  833.             break;
  834.         case cbHamPickle:
  835.             CheckButton( window, cbHamPickle+standardDITL );
  836.             newFood->ham.pickle = !(newFood->ham.pickle);
  837.             break;
  838.     }
  839. }
  840.  
  841. /** This function is a hack.  You should do a better job with it. =)  **/
  842. void    FindWindowToUpdate( WindowPtr window )
  843. {
  844.     long        ID;
  845.     GrafPtr        old;
  846.     
  847.     // I store the window number in the ref con of the window (see MyGetNewDialogFont())
  848.     // Normally I have a function to do this, but in this case, I only call it once.
  849.     ID = (long) GetWRefCon( window );
  850.     
  851.     GetPort( &old );
  852.  
  853.     SetPort( window );
  854.     
  855.     switch (ID)
  856.     {
  857.         case wPreferences:
  858.             // This is a weird thing.  Normally you stick redrawing functions within the BeginUpdate()
  859.             // and EndUpdate() calls, but here, if I try, they don't draw correctly.  It's possible
  860.             // that the dialog manager draws over anything I draw, and that's why, but I haven't
  861.             // run across that in any other program I've written.  Any ideas anyone?
  862.             BeginUpdate( window );
  863.             EndUpdate( window );
  864.     
  865.             FrameOptions( (DialogPtr) window );
  866.             break;
  867.         default:
  868.             break;
  869.     }
  870.  
  871.     SetPort( old );
  872. }
  873. /** THE END!!!!! **/
  874.